package edu.neu.swc.commerce.service.communication;

import com.google.gson.Gson;
import edu.neu.swc.commerce.vo.JwtToken;
import edu.neu.swc.commerce.vo.UsernameAndPassword;
import feign.Feign;
import feign.Logger;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.swing.*;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Random;

/**
 * <h1>使用Feign的原生Api，OpenFeign = Feign + Ribbon</h1>
 */
@Slf4j
@Service
public class UseFeignApi {

    private final DiscoveryClient discoveryClient;

    public UseFeignApi(DiscoveryClient discoveryClient) {
        this.discoveryClient = discoveryClient;
    }

    /**
     * <h2>使用Feign的原生Api去调用远端服务</h2>
     * Feign的默认配置初始化，设置自定义配置，生成代理对象
     */
    public JwtToken thinkingInFeign(
            UsernameAndPassword usernameAndPassword
    ){
        //通过反射去
        String serviceId = null;
        Annotation[] annotations = AuthorityFeignClient.class.getAnnotations();
        for(Annotation annotation : annotations){
            if(annotation.annotationType().equals(FeignClient.class)){
                serviceId = ((FeignClient) annotation).value();
                log.info("get service id from Authority Feign Client:[{}]",serviceId);
                break;
            }
        }

        //如果服务ID不存在
        if(null == serviceId){
            throw new RuntimeException("can not get Service Id");
        }

        //通过ServiceId去拿到可用的服务实例
        List<ServiceInstance> targetInstances = discoveryClient.getInstances(serviceId);

        if(CollectionUtils.isEmpty(targetInstances)){
            throw new RuntimeException("can not get target instance from service Id :" + serviceId);
        }

        //随机挑选一个实例，负载均衡
        ServiceInstance randomInstance = targetInstances.get(
                new Random().nextInt(targetInstances.size())
        );

        log.info("choose service instance:[{}],[{}],[{}]", serviceId,
                randomInstance.getHost(),randomInstance.getPort());

        //Feign 客户端初始化，必须要配置encoder和decoder，contract
        AuthorityFeignClient feignClient = Feign.builder()
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logLevel(Logger.Level.FULL)
                .contract(new SpringMvcContract())
                .target(
                        AuthorityFeignClient.class,
                        String.format("http://%s:%s",
                                randomInstance.getHost(),
                                randomInstance.getPort())
                );

        return feignClient.getTokenByFeign(usernameAndPassword);
    }
}
